﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace IML
{
    public enum NodeType
    {
        Rule,
        Token
    }

    public enum TokenType
    {
        Symbol,
        Identifier,
        Int,
        Real,
        Hex
    }

    public abstract class Node
    {
        public NodeType NodeType;
        public IList<Node> Children;

        protected Node(NodeType type)
        {
            this.NodeType = type;
        }
    }

    public class Rule : Node
    {
        public string Name;
        
        public Rule(string name, NodeType type) : base(NodeType.Rule)
        {
            Name = name;
            NodeType = type;
        }
    }

    public class Token : Node
    {
        public TokenType TokenType;
        private static string _lexem { get; set; }
        private static int _lineNum { get; set; }


        protected Token(string lexem, int lineNum, TokenType tType) : base(NodeType.Token)
        {
            this.TokenType = tType;
            _lexem = lexem;
            _lineNum = lineNum;
        }

        public static Token NewToken(string lexem, int lineNum)
        {
            if (Regex.IsMatch(lexem, "^[,;:*<>(){}[\\]-]$"))
                return new SymbolToken(lexem, lineNum);
            if (Regex.IsMatch(lexem, "^#[0-9a-f]{6}$"))
                return new HexToken(lexem, lineNum);
            //if (Regex.IsMatch(lexem, "^(+|-)?[0-9]+.[0-9]+$"))
            //    return new RealToken(lexem, lineNum);
            //if (Regex.IsMatch(lexem, "^(+|-)?[0-9]+/[1-9][0-9]*$"))
            //    return new RealToken(lexem, lineNum);
            //if (Regex.IsMatch(lexem, "^(+|-)?[0-9]+$"))
            //    return new IntToken(lexem, lineNum);
            if (Regex.IsMatch(lexem, "^[a-z0-9_]+$"))
                return new IdentifierToken(lexem, lineNum);
            return null;
        }
    }

    public class SymbolToken : Token
    {
        public SymbolToken(string lexem, int lineNum) : base(lexem, lineNum, TokenType.Symbol) { }
    }

    public class IdentifierToken : Token
    {
        public IdentifierToken(string lexem, int lineNum) : base(lexem, lineNum, TokenType.Identifier) { }
    }

    public class IntToken : Token
    {
        public IntToken(string lexem, int lineNum) : base(lexem, lineNum, TokenType.Int) { }
    }

    public class RealToken : Token
    {
        public RealToken(string lexem, int lineNum) : base(lexem, lineNum, TokenType.Real) { }
    }

    public class HexToken : Token
    {
        public HexToken(string lexem, int lineNum) : base(lexem, lineNum, TokenType.Hex) { }
    }
}